#include "VSRectAnimBlend.h"
#include "VSGraphicInclude.h"
using namespace VSEngine2;
IMPLEMENT_RTTI(VSRectAnimBlend,VSTwoParamAnimBlend)
static bool gs_bStreamRegistered_VSRectAnimBlend= VSRectAnimBlend::RegisterMainFactory();
bool VSRectAnimBlend::ms_bRegisterMainFactory = false;
bool VSRectAnimBlend::RegisterMainFactory()
{
	if (!ms_bRegisterMainFactory)
	{ 
		VSMain::AddInitialFuntion(VSRectAnimBlend::InitialClassFactory); 
		ms_bRegisterMainFactory = true;
	} 
	return ms_bRegisterMainFactory;

}
bool VSRectAnimBlend::InitialClassFactory()
{
	ms_ClassFactory.AddElement(ms_Type.GetName(),FactoryFunc);

	return 1;
}
VSObject * VSRectAnimBlend::FactoryFunc()
{
	return VS_NEW VSRectAnimBlend;

}
VSRectAnimBlend::~VSRectAnimBlend()
{

}
VSRectAnimBlend::VSRectAnimBlend()
{

}
VSRectAnimBlend::VSRectAnimBlend(const VSUsedName & ShowName,VSAnimTree * pAnimTree)
:VSTwoParamAnimBlend(ShowName,pAnimTree)
{


	for (unsigned int i = CL_LEFT_TOP ; i < CL_MAX ; i++)
	{
		VSString InputName = _T("Child");
		VSString ID = IntToString(m_pInput.GetNum()); 
		InputName += ID;
		VSInputNode * pInputNode = NULL;
		pInputNode = VS_NEW VSInputNode(VSPutNode::AVT_ANIM,InputName,this);
		VSMAC_ASSERT(pInputNode);
		m_pInput.AddElement(pInputNode);

		m_NodeCrossFadingTime.AddElement(0.0f);

	}
	unsigned int BoneNum = GetSkelectonMeshNode()->GetSkelecton()->GetBoneNum();
	m_BlendBoneMatrix[0].SetBufferNum(BoneNum);
	m_BlendBoneMatrix[1].SetBufferNum(BoneNum);
}
bool VSRectAnimBlend::Link(VSStream & rStream)
{
	if (!VSTwoParamAnimBlend::Link(rStream))
	{
		return 0;
	}
	unsigned int BoneNum = GetSkelectonMeshNode()->GetSkelecton()->GetBoneNum();
	m_BlendBoneMatrix[0].SetBufferNum(BoneNum);
	m_BlendBoneMatrix[1].SetBufferNum(BoneNum);
	return 1;
}
bool VSRectAnimBlend::Clone(const VSObject *pObject,unsigned int uiType)
{
	const VSRectAnimBlend* Temp = DynamicCast<VSRectAnimBlend>(pObject); 
	if(!Temp)
		return 0;
	if(VSTwoParamAnimBlend::Clone(pObject,uiType))
	{
		m_BlendBoneMatrix[0] = Temp->m_BlendBoneMatrix[0];
		m_BlendBoneMatrix[1] = Temp->m_BlendBoneMatrix[1];
		return 1;
	}
	else
	{
		return 0;
	}
}
bool VSRectAnimBlend::ComputeOutBoneMatrix(double dAppTime)
{
	VSREAL fInternal[2];
	for (unsigned int i = 0 ; i < 2 ; i++)
	{
		fInternal[i] = m_fParamMax[i] - m_fParamMin[i];
		
		if (fInternal[i] < EPSILON_E4)
		{
			return 0;
		}
	}
	
	if (m_uiCrossFadingType == CFT_SMOOTH)
	{

		float fWeight[2];
		for (unsigned int i = 0 ; i < 2 ; i++)
		{
			fWeight[i] = (m_fParam[i] - m_fParamMin[i]) / fInternal[i];
		}

		VSInputNode* pInputNode0 = GetInputNode(0);
		VSInputNode* pInputNode1 = GetInputNode(1);
		VSInputNode* pInputNode2 = GetInputNode(2);
		VSInputNode* pInputNode3 = GetInputNode(3);
		if(pInputNode1->GetOutputLink() && pInputNode2->GetOutputLink() 
			&& pInputNode0->GetOutputLink() && pInputNode3->GetOutputLink())
		{
			VSAnimFunction *pAnimBaseFunction1 = (VSAnimFunction *)pInputNode1->GetOutputLink()->GetOwner();
			VSAnimFunction *pAnimBaseFunction2 = (VSAnimFunction *)pInputNode2->GetOutputLink()->GetOwner();
			VSAnimFunction *pAnimBaseFunction0 = (VSAnimFunction *)pInputNode0->GetOutputLink()->GetOwner();
			VSAnimFunction *pAnimBaseFunction3 = (VSAnimFunction *)pInputNode3->GetOutputLink()->GetOwner();
			LineBlendTwo(&m_BlendBoneMatrix[0],pAnimBaseFunction0,pAnimBaseFunction1,fWeight[0]);
			LineBlendTwo(&m_BlendBoneMatrix[1],pAnimBaseFunction2,pAnimBaseFunction3,fWeight[0]);
			LineBlendTwo(&m_BoneOutPut,&m_BlendBoneMatrix[0],&m_BlendBoneMatrix[1],fWeight[1]);
		}
	}
	else if (m_uiCrossFadingType == CFT_IMMEDIATE)
	{
		unsigned int uiUseIndex;
		if (m_fParamMax[0] >= m_fParamMin[0] && m_fParamMax[0] < m_fParamMax[0]
		&& m_fParamMax[1] >= m_fParamMin[1] && m_fParamMax[1] < m_fParamMax[1])
		{
			uiUseIndex = CL_LEFT_TOP;
		}
		else if (m_fParamMax[0] >= m_fParamMin[0] && m_fParamMax[0] < m_fParamMax[0]
		&& m_fParamMax[1] >= m_fParamMax[1])
		{
			uiUseIndex = CL_LEFT_BOTTOM;
		}
		else if (m_fParamMax[1] >= m_fParamMin[1] && m_fParamMax[1] < m_fParamMax[1]
		&& m_fParamMax[0] >= m_fParamMax[0])
		{
			uiUseIndex = CL_RIGTH_TOP;
		}
		else
		{
			uiUseIndex = CL_RIGHT_BOTTOM;
		}
		if (m_uiLastAnimIndex == VSMAX_INTEGER)
		{
			m_uiLastAnimIndex = uiUseIndex;		
		}


		if (m_uiLastAnimIndex != uiUseIndex)
		{
			if (m_fCrossFadingTime < m_NodeCrossFadingTime[uiUseIndex])
			{
				VSREAL fWeight = 0.0f;
// 				if (m_NodeCrossFadingTime[uiUseIndex] > EPSILON_E4)
// 				{
				fWeight =m_fCrossFadingTime / m_NodeCrossFadingTime[uiUseIndex];
/*				}*/

				VSInputNode* pInputNode1 = GetInputNode(m_uiLastAnimIndex);
				VSInputNode* pInputNode2 = GetInputNode(uiUseIndex);
				if(pInputNode1->GetOutputLink() && pInputNode2->GetOutputLink())
				{
					VSAnimFunction *pAnimBaseFunction1 = (VSAnimFunction *)pInputNode1->GetOutputLink()->GetOwner();
					VSAnimFunction *pAnimBaseFunction2 = (VSAnimFunction *)pInputNode2->GetOutputLink()->GetOwner();
					LineBlendTwo(this,pAnimBaseFunction1,pAnimBaseFunction2,fWeight);
				}
				m_fCrossFadingTime += (VSREAL)m_dIntervalTime;
			}
			else 
			{
				m_uiLastAnimIndex = uiUseIndex;
				m_fCrossFadingTime = 0.0f;

				VSInputNode* pInputNode1 = GetInputNode(uiUseIndex);
				if(pInputNode1->GetOutputLink())
				{
					VSAnimFunction *pAnimBaseFunction1 = (VSAnimFunction *)pInputNode1->GetOutputLink()->GetOwner();
					LineBlendTwo(this,pAnimBaseFunction1,NULL,0.0f);
				}
			}
		}
		else
		{
			VSInputNode* pInputNode1 = GetInputNode(uiUseIndex);
			if(pInputNode1->GetOutputLink())
			{
				VSAnimFunction *pAnimBaseFunction1 = (VSAnimFunction *)pInputNode1->GetOutputLink()->GetOwner();
				LineBlendTwo(this,pAnimBaseFunction1,NULL,0.0f);
			}

		}



	}

	return 1;
}